// 序列化表单
// loading indicator 对应有 读取数据 和 保存数据 两种
// 调用 autoInit 初始化表达内的各种控件
define(function(require, exports, module) {
	var $ = require('bigfoot/common'),
		_validator = require('bigfoot/dhtml/form/validator'),
		request = require('bigfoot/dhtml/request'),
		autoInit = require('bigfoot/form/autoInit');

	// 封装了 onSubmit 事件
	module.exports = {
		init : function(){
			if(!this.formEl)throw '未设置表单元素！';
			if(!this.action)this.action = this.formEl.action; // 如果不通过 js 设置 url，则读取 HTML 上的 action 属性
			if(!this.action)throw '未设置接口地址！';

	    	var validator = Object.create(_validator);
	    	validator.formEl = this.formEl;
	    	validator.init();

	    	this.validator = validator;
 
    		this.formEl.on('submit', onSubmit.bind(this));

    		autoInit.initCalendar(this.formEl);
    		autoInit.initImgPerview(this.formEl);
    		autoInit.whenpresscheckCharLength(this.formEl);
    		
    		this.formEl.regChildClick('.return', back);
		}
		,checkAllFields : function(){
			return this.validator.checkAllFields();
		},
		// @overidable
		showLoadingIndicator : function(){
			this.loadingIndicator.removeCls('hide');
		},		
		// @overidable
		hideLoadingIndicator : function(){
			this.loadingIndicator.addCls('hide');
		},
		autoDetectMehtodById : function(){
			if(/id=\d+/.test(location.search)){
				// 有 id 是 update
				this.PUT = true;
			}else{
				// 没 id 是 create 
			}
		}
	};
	
	/**
	 * 返回
	 */
	function back(e){
		e.preventDefault();
		window.history.go(-1);
	}

	function onSubmit(e){
		e.preventDefault();
		
		if(!this.checkAllFields())return; // 表单验证不通过，返回
			
		// if(this.beforSubmit && this.beforSubmit(this.formEl, e) === false)return;
		if(this.beforeSubmit && this.beforeSubmit(this.formEl, e) === false)return;

		console.log('提交表单中……');
		this.loadingIndicator && this.showLoadingIndicator();

		this.formData = serializeForm(this.formEl); // 保存表单数据引用
		
		// htmlEditor 没有标识自己不存在，@todo
		if(window.bf.htmlEditor)
			this.formData.content = encodeURIComponent(window.bf.htmlEditor.getValue());			
		
		
		if(this.PUT){
			var xhr = Object.create(request.xhr);
			xhr.url = this.action;
			xhr.params = this.formData;
			xhr.httpMethod = 'PUT';
			xhr.onSuccuess = onSubmitSuccuess.bind(this);
			xhr.request();
		}else{
			$.post(this.action, onSubmitSuccuess.bind(this), this.formData);
		}

	}

	function onSubmitSuccuess(json){
		if(!this.onSubmitSuccuess){

			if(json.isOk) $.msg('保存成功！', function(){
				//@todo 返回
//				window.history.back();
				// var iframe = window.document.querySelector('iframe[name="iframepage"]');
				// if (iframe){
				// 	iframe.contentDocument.location.reload();
				// }else window.location.reload();
				 // window.location.reload();
			});
			else $.alert('保存失败！');
		}else this.onSubmitSuccuess(json);

		this.loadingIndicator && this.hideLoadingIndicator();
	}
	function onSubmitFail(err){
		alert('保存失败！原因' + err);
		this.loadingIndicator && this.hideLoadingIndicator();
	}

	function serializeForm(formEl, isStringOutput, isIgnroEmpty /* 是否忽略空字符串的字段 */){
		var formData = {};
		
		eachChild4form(formEl, function(el){

			var elType = el.type;
			
			if(elType == "text" || elType == "hidden" || elType == "password" || elType == "textarea"){
		
				formData[el.name] = getPrimitives(el.value);

			}else if(elType == "radio" || elType == "checkbox"){
				
				if(el.checked)// 选中才会加入数据
					formData[el.name] = getPrimitives(el.value);

			}else if(elType == "select-one" || elType == "select-multiple"){

				for(var opt, optValue, p = 0, q = el.options.length; p < q; p++){
					opt = el.options[p];
					if (opt.selected) {
						optValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttribute('value') !== null
						optValue = optValue ? opt.value : opt.text;			
						
						formData[el.name] = getPrimitives(optValue);
					}
				}
			}
		});

		if(isIgnroEmpty){
			for(var i in formData){
				if(formData[i] === "")
					delete formData[i];
			}
		}

		return isStringOutput ? utils.json2url(formData) : formData;
	}
	
	/**
	 * 输入参数，还原它的primitive值。有点类似 eval() 的作用，却不使用 eval()。
	 * @param  {Mixed} v
	 * @return {Mixed}
	 */
	function getPrimitives(v){
		if(v){
			if(v == 'true' ) return true;
			if(v == 'false') return false;
			if(v.toString() == (new Date(v)).toString()) return new Date(v); // v is a date but in Stirng Type
	      	if(v == String(Number(v))) return Number(v);
		}
	  	return v;
	}

	// 判断form的内容是否有改变
	function isFormChanged(formEl){
		var i = 0;
		eachChild4form(formEl, function(el){
			switch(el.type){
	            case "text":
	            case "hidden":
	            case "password":
	            case "textarea":
	                if (el.defaultValue != el.value) return true;
	            break;
	            case "radio":
	            case "checkbox":
	                if (el.defaultChecked != el.checked) return true;
	            break;
	            case "select-one":
	                i = 1;
	            case "select-multiple":
	                opts = el.options;
	                for (;i < opts.length; i++)
	                	if (opts[i].defaultSelected != opts[i].selected)return true;
	            break;
			}
		});

		return false;
	}

	// 遍历表单
	function eachChild4form(formEl, fn){
		// 豁免：没有 name 属性的不要；禁止了的不要；特定的字段不要
		// !el.checked // 未选择的要来干嘛？?
		var ignore = /file|undefined|reset|button|submit/i;
		
		for(var el, i = 0, j = formEl.elements.length; i < j; i++){
			el = formEl.elements[i];
			if(!el.name || el.disabled || ignore.test(el.type))continue;
			fn(el, i);
		}
	}

	module.exports.serializeForm = serializeForm;
});